#include <bsl_err.h>
#include <bsl_sal.h>
#include <crypt_algid.h>
#include <crypt_eal_pkey.h>
#include <crypt_eal_provider.h>
#include <crypt_errno.h>
#include <crypt_rsa.h>
#include <crypt_params_key.h>
#include <securec.h>

#include <setjmp.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include <cmocka.h>

#include "helper.h"
#include "test_rsa.h"

#define GROUP_TEST_MAX 100

#define CRYPT_EAL_PKEY_KEYMGMT_OPERATE 0
#define CRYPT_EAL_PKEY_CIPHER_OPERATE  1
#define CRYPT_EAL_PKEY_EXCH_OPERATE    2
#define CRYPT_EAL_PKEY_SIGN_OPERATE    4

int SDV_KAE_RSA_PARA_API_TC002_VEC[] = {
    1023,
    78,
    16385,
};

static CRYPT_EAL_LibCtx *CreateLoadLibCtx()
{
    CRYPT_EAL_LibCtx *libctx = CRYPT_EAL_LibCtxNew();
    assert_non_null(libctx);
    assert_int_equal(CRYPT_EAL_ProviderSetLoadPath(libctx, "../../build"), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_ProviderLoad(libctx, BSL_SAL_LIB_FMT_LIBSO, "kae_provider", NULL, NULL), CRYPT_SUCCESS);
    return libctx;
}

static void SDV_KAE_RSA_PROVIDER_LOAD(void **state)
{
    (void)state;
    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_LibCtxFree(libctx);
}

void SDV_KAE_RSA_NEW_API_TC001(void **state)
{
    (void)state;
    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    for (int i = 0; i < 100; i++) {
        CRYPT_EAL_PkeyCtx *pkey =
            CRYPT_EAL_ProviderPkeyNewCtx(libctx, CRYPT_PKEY_RSA, CRYPT_EAL_PKEY_KEYMGMT_OPERATE, "provider=kaev1");
        assert_non_null(pkey);
        CRYPT_EAL_PkeyFreeCtx(pkey);
    }
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_RSA_PARA_API_TC001(void **state)
{
    (void)state;

    uint8_t e[] = {1, 0, 1};
    uint8_t e2[] = {1, 0};
    uint8_t e0[] = {0, 0, 0};
    uint8_t longE[1025] = {0};
    longE[0] = 0x01;
    longE[1024] = 0x01;
    CRYPT_EAL_PkeyPara para = {0};

    SetRsaPara(&para, e, 3, 1024);

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_PkeyCtx *pkey =
        CRYPT_EAL_ProviderPkeyNewCtx(libctx, CRYPT_PKEY_RSA, CRYPT_EAL_PKEY_KEYMGMT_OPERATE, "provider=kaev1");
    assert_non_null(pkey);

    para.para.rsaPara.e = NULL;
    assert_int_equal(CRYPT_EAL_PkeySetPara(pkey, &para), CRYPT_EAL_ERR_NEW_PARA_FAIL);

    para.para.rsaPara.eLen = 0;
    assert_int_equal(CRYPT_EAL_PkeySetPara(pkey, &para), CRYPT_EAL_ERR_NEW_PARA_FAIL);

    para.para.rsaPara.e = e0;
    para.para.rsaPara.eLen = 1;
    assert_int_equal(CRYPT_EAL_PkeySetPara(pkey, &para), CRYPT_RSA_ERR_E_VALUE);

    para.para.rsaPara.eLen = 2;
    para.para.rsaPara.e = e2;
    assert_int_equal(CRYPT_EAL_PkeySetPara(pkey, &para), CRYPT_RSA_ERR_E_VALUE);

    para.para.rsaPara.eLen = 1025;
    para.para.rsaPara.e = longE;
    assert_int_equal(CRYPT_EAL_PkeySetPara(pkey, &para), CRYPT_EAL_ERR_NEW_PARA_FAIL);

    CRYPT_EAL_PkeyFreeCtx(pkey);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_RSA_PARA_API_TC002(void **state)
{
    int32_t *bits = *state;
    ;

    uint8_t e[] = {1, 0, 1};
    CRYPT_EAL_PkeyPara para = {0};

    SetRsaPara(&para, e, 3, *bits);

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_PkeyCtx *pkey =
        CRYPT_EAL_ProviderPkeyNewCtx(libctx, CRYPT_PKEY_RSA, CRYPT_EAL_PKEY_KEYMGMT_OPERATE, "provider=kaev1");
    assert_non_null(pkey);

    assert_int_equal(CRYPT_EAL_PkeySetPara(pkey, &para), CRYPT_EAL_ERR_NEW_PARA_FAIL);

    CRYPT_EAL_PkeyFreeCtx(pkey);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_RSA_PARA_API_TC003(void **state)
{
    (void)state;
    uint8_t e3[] = {1, 0, 1};
    uint8_t e5[] = {1, 0, 0, 0, 1};
    uint8_t e7[] = {1, 0, 0, 0, 0, 0, 1};
    CRYPT_EAL_PkeyPara para = {0};

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_PkeyCtx *pkey =
        CRYPT_EAL_ProviderPkeyNewCtx(libctx, CRYPT_PKEY_RSA, CRYPT_EAL_PKEY_KEYMGMT_OPERATE, "provider=kaev1");
    assert_non_null(pkey);

    SetRsaPara(&para, e3, 3, 1024);
    assert_int_equal(CRYPT_EAL_PkeySetPara(pkey, &para), CRYPT_SUCCESS);

    para.para.rsaPara.bits = 1025;
    assert_int_equal(CRYPT_EAL_PkeySetPara(pkey, &para), CRYPT_SUCCESS);

    SetRsaPara(&para, e5, 5, 5120);
    assert_int_equal(CRYPT_EAL_PkeySetPara(pkey, &para), CRYPT_SUCCESS);

    SetRsaPara(&para, e7, 7, 16384);
    assert_int_equal(CRYPT_EAL_PkeySetPara(pkey, &para), CRYPT_SUCCESS);

    CRYPT_EAL_PkeyFreeCtx(pkey);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_RSA_GEN_API_TC001(void **state)
{
    (void)state;

    uint8_t e[] = {1, 0, 1};
    CRYPT_EAL_PkeyPara para = {0};

    SetRsaPara(&para, e, 3, 1024);

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_PkeyCtx *pkey =
        CRYPT_EAL_ProviderPkeyNewCtx(libctx, CRYPT_PKEY_RSA, CRYPT_EAL_PKEY_KEYMGMT_OPERATE, "provider=kaev1");
    assert_non_null(pkey);

    assert_int_equal(CRYPT_EAL_PkeySetPara(pkey, &para), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_PkeyGen(pkey), CRYPT_NO_REGIST_RAND);

    CRYPT_EAL_PkeyFreeCtx(pkey);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_RSA_GET_PUB_API_TC001(void **state)
{
    (void)state;

    uint8_t e[] = {1, 0, 1};
    CRYPT_EAL_PkeyPara para = {0};
    CRYPT_EAL_PkeyPub pubKey = {0};
    uint8_t pubE[600];
    uint8_t pubN[600];

    SetRsaPara(&para, e, 3, 1024);
    SetRsaPubKey(&pubKey, pubE, 600, pubN, 600); // 600 bytes > 1024 bits

    assert_int_equal(RandInit(), CRYPT_SUCCESS);

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_PkeyCtx *pkey =
        CRYPT_EAL_ProviderPkeyNewCtx(libctx, CRYPT_PKEY_RSA, CRYPT_EAL_PKEY_KEYMGMT_OPERATE, "provider=kaev1");
    assert_non_null(pkey);

    assert_int_equal(CRYPT_EAL_PkeyGetPub(pkey, &pubKey), CRYPT_NULL_INPUT);

    assert_int_equal(CRYPT_EAL_PkeySetPara(pkey, &para), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_PkeyGen(pkey), CRYPT_SUCCESS);

    assert_int_equal(CRYPT_EAL_PkeyGetPub(NULL, &pubKey), CRYPT_NULL_INPUT);
    assert_int_equal(CRYPT_EAL_PkeyGetPub(pkey, NULL), CRYPT_NULL_INPUT);

    /* n = NULL */
    pubKey.key.rsaPub.n = NULL;
    assert_int_equal(CRYPT_EAL_PkeyGetPub(pkey, &pubKey), CRYPT_NULL_INPUT);
    pubKey.key.rsaPub.n = pubN;

    /* n  and nLen = 0 */
    pubKey.key.rsaPub.nLen = 0;
    assert_int_equal(CRYPT_EAL_PkeyGetPub(pkey, &pubKey), CRYPT_BN_BUFF_LEN_NOT_ENOUGH);
    pubKey.key.rsaPub.nLen = 600;

    /* e = NULL */
    pubKey.key.rsaPub.e = NULL;
    assert_int_equal(CRYPT_EAL_PkeyGetPub(pkey, &pubKey), CRYPT_NULL_INPUT);
    pubKey.key.rsaPub.e = pubE;

    /* e , eLen = 0 */
    pubKey.key.rsaPub.eLen = 0;
    assert_int_equal(CRYPT_EAL_PkeyGetPub(pkey, &pubKey), CRYPT_BN_BUFF_LEN_NOT_ENOUGH);

    CRYPT_EAL_RandDeinit();
    CRYPT_EAL_PkeyFreeCtx(pkey);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_RSA_GET_PRV_API_TC001()
{
    CRYPT_EAL_PkeyPrv prvKey = {0};

    CRYPT_EAL_PkeyPara para = {0};
    uint8_t e[] = {1, 0, 1};
    uint8_t prvD[600];
    uint8_t prvN[600];
    uint8_t prvP[600];
    uint8_t prvQ[600];

    SetRsaPrvKey(&prvKey, prvN, 600, prvD, 600);
    SetRsaPara(&para, e, 3, 1024);

    assert_int_equal(RandInit(), CRYPT_SUCCESS);

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_PkeyCtx *pkey =
        CRYPT_EAL_ProviderPkeyNewCtx(libctx, CRYPT_PKEY_RSA, CRYPT_EAL_PKEY_KEYMGMT_OPERATE, "provider=kaev1");
    assert_non_null(pkey);

    /* Missing private key */
    assert_int_equal(CRYPT_EAL_PkeyGetPrv(pkey, &prvKey), CRYPT_NULL_INPUT);

    assert_int_equal(CRYPT_EAL_PkeySetPara(pkey, &para), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_PkeyGen(pkey), CRYPT_SUCCESS);

    assert_int_equal(CRYPT_EAL_PkeyGetPrv(NULL, &prvKey), CRYPT_NULL_INPUT);
    assert_int_equal(CRYPT_EAL_PkeyGetPrv(pkey, NULL), CRYPT_NULL_INPUT);

    /* p is NULL and q is NULL */
    assert_int_equal(CRYPT_EAL_PkeyGetPrv(pkey, &prvKey), CRYPT_SUCCESS);

    /* p = NULL and q  */
    prvKey.key.rsaPrv.q = prvQ;
    prvKey.key.rsaPrv.qLen = 600;
    assert_int_equal(CRYPT_EAL_PkeyGetPrv(pkey, &prvKey), CRYPT_NULL_INPUT);

    /* p  and q  */
    prvKey.key.rsaPrv.p = prvP;
    prvKey.key.rsaPrv.pLen = 600;
    assert_int_equal(CRYPT_EAL_PkeyGetPrv(pkey, &prvKey), CRYPT_SUCCESS);

    /* d = NULL */
    prvKey.key.rsaPrv.d = NULL;
    assert_int_equal(CRYPT_EAL_PkeyGetPrv(pkey, &prvKey), CRYPT_NULL_INPUT);

    CRYPT_EAL_RandDeinit();
    CRYPT_EAL_PkeyFreeCtx(pkey);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_RSA_SET_PRV_API_TC001(void **state)
{
    (void)state;

    CRYPT_EAL_PkeyPara para = {0};
    CRYPT_EAL_PkeyPrv prvKey = {0};
    uint8_t e[] = {1, 0, 1};
    uint8_t prvD[600];
    uint8_t prvN[2500];
    uint8_t prvP[600];
    uint8_t prvQ[600];
    uint8_t prvE[600];

    SetRsaPrvKey(&prvKey, prvN, 600, prvD, 600);
    SetRsaPara(&para, e, 3, 1024);

    assert_int_equal(RandInit(), CRYPT_SUCCESS);

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_PkeyCtx *pkeyA =
        CRYPT_EAL_ProviderPkeyNewCtx(libctx, CRYPT_PKEY_RSA, CRYPT_EAL_PKEY_KEYMGMT_OPERATE, "provider=kaev1");
    assert_non_null(pkeyA);
    CRYPT_EAL_PkeyCtx *pkeyB =
        CRYPT_EAL_ProviderPkeyNewCtx(libctx, CRYPT_PKEY_RSA, CRYPT_EAL_PKEY_KEYMGMT_OPERATE, "provider=kaev1");
    assert_non_null(pkeyB);

    assert_int_equal(CRYPT_EAL_PkeySetPara(pkeyA, &para), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_PkeySetPara(pkeyB, &para), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_PkeyGen(pkeyA), CRYPT_SUCCESS);

    assert_int_equal(CRYPT_EAL_PkeyGetPrv(pkeyA, &prvKey), CRYPT_SUCCESS);

    (void)memset_s(prvD, sizeof(prvD), 0x00, sizeof(prvD));
    assert_int_equal(CRYPT_EAL_PkeySetPrv(pkeyB, &prvKey), CRYPT_RSA_ERR_INPUT_VALUE);

    prvD[sizeof(prvD) - 1] = 1;
    assert_int_equal(CRYPT_EAL_PkeySetPrv(pkeyB, &prvKey), CRYPT_RSA_ERR_INPUT_VALUE);

    assert_int_equal(CRYPT_EAL_PkeyGetPrv(pkeyA, &prvKey), CRYPT_SUCCESS);
    (void)memset_s(prvN, sizeof(prvN), 0x00, sizeof(prvN));
    assert_int_equal(CRYPT_EAL_PkeySetPrv(pkeyB, &prvKey), CRYPT_RSA_ERR_KEY_BITS);

    prvKey.key.rsaPrv.q = prvQ;
    prvKey.key.rsaPrv.qLen = 600; // 600 bytes > 1024 bits
    prvKey.key.rsaPrv.p = prvP;
    prvKey.key.rsaPrv.pLen = 600; // 600 bytes > 1024 bits

    assert_int_equal(CRYPT_EAL_PkeyGetPrv(pkeyA, &prvKey), CRYPT_SUCCESS);
    (void)memset_s(prvP, sizeof(prvP), 0x00, sizeof(prvP));
    assert_int_equal(CRYPT_EAL_PkeySetPrv(pkeyB, &prvKey), CRYPT_RSA_ERR_INPUT_VALUE);

    assert_int_equal(CRYPT_EAL_PkeyGetPrv(pkeyA, &prvKey), CRYPT_SUCCESS);
    (void)memset_s(prvQ, sizeof(prvQ), 0x00, sizeof(prvQ));
    assert_int_equal(CRYPT_EAL_PkeySetPrv(pkeyB, &prvKey), CRYPT_RSA_ERR_INPUT_VALUE);

    assert_int_equal(CRYPT_EAL_PkeyGetPrv(pkeyA, &prvKey), CRYPT_SUCCESS);
    prvKey.key.rsaPrv.nLen = 2049; // 2049 > MAx n len
    assert_int_equal(CRYPT_EAL_PkeySetPrv(pkeyB, &prvKey), CRYPT_RSA_ERR_KEY_BITS);

    prvKey.key.rsaPrv.nLen = 600; // 600 bytes > 1024 bits
    assert_int_equal(CRYPT_EAL_PkeyGetPrv(pkeyA, &prvKey), CRYPT_SUCCESS);
    prvKey.key.rsaPrv.p = NULL;
    assert_int_equal(CRYPT_EAL_PkeySetPrv(pkeyB, &prvKey), CRYPT_RSA_NO_KEY_INFO);
    prvKey.key.rsaPrv.p = prvP;

    prvKey.key.rsaPrv.e = prvE;
    prvKey.key.rsaPrv.eLen = 600;
    assert_int_equal(CRYPT_EAL_PkeyGetPrv(pkeyA, &prvKey), CRYPT_SUCCESS);
    assert_int_equal(prvKey.key.rsaPrv.eLen, 3);
    assert_memory_equal(prvKey.key.rsaPrv.e, e, 3);

    assert_int_equal(CRYPT_EAL_PkeySetPrv(pkeyB, &prvKey), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_PkeyGetPrv(pkeyB, &prvKey), CRYPT_SUCCESS);
    assert_int_equal(prvKey.key.rsaPrv.eLen, 3);
    assert_memory_equal(prvKey.key.rsaPrv.e, e, 3);

    CRYPT_EAL_RandDeinit();
    CRYPT_EAL_PkeyFreeCtx(pkeyA);
    CRYPT_EAL_PkeyFreeCtx(pkeyB);
    CRYPT_EAL_LibCtxFree(libctx);
}

void SDV_KAE_RSA_SET_PRV_API_TC002(void **state)
{
    (void)state;

    uint8_t prvD[2050]; // max rsa key len is 16384 bits, 16384/8 = 2048, 2050 > 2048
    uint8_t prvN[2050]; // max rsa key len is 16384 bits, 16384/8 = 2048, 2050 > 2048
    CRYPT_EAL_PkeyPrv prvKey = {0};

    (void)memset_s(prvD, sizeof(prvD), 0xff, sizeof(prvD));
    (void)memset_s(prvN, sizeof(prvN), 0xff, sizeof(prvN));
    SetRsaPrvKey(&prvKey, prvN, RSA_MIN_KEYLEN, prvD, RSA_MIN_KEYLEN);

    assert_int_equal(RandInit(), CRYPT_SUCCESS);

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_PkeyCtx *pkey =
        CRYPT_EAL_ProviderPkeyNewCtx(libctx, CRYPT_PKEY_RSA, CRYPT_EAL_PKEY_KEYMGMT_OPERATE, "provider=kaev1");
    assert_non_null(pkey);

    assert_int_equal(CRYPT_EAL_PkeySetPrv(pkey, &prvKey), CRYPT_RSA_ERR_INPUT_VALUE);

    prvKey.key.rsaPrv.nLen = RSA_MIN_KEYLEN - 1;
    assert_int_equal(CRYPT_EAL_PkeySetPrv(pkey, &prvKey), CRYPT_RSA_ERR_KEY_BITS);

    prvKey.key.rsaPrv.nLen = RSA_MAX_KEYLEN + 1;
    assert_int_equal(CRYPT_EAL_PkeySetPrv(pkey, &prvKey), CRYPT_RSA_ERR_KEY_BITS);

    prvKey.key.rsaPrv.nLen = RSA_MAX_KEYLEN;
    prvKey.key.rsaPrv.dLen = RSA_MAX_KEYLEN + 1;
    assert_int_equal(CRYPT_EAL_PkeySetPrv(pkey, &prvKey), CRYPT_RSA_ERR_KEY_BITS);

    prvKey.key.rsaPrv.nLen = RSA_MIN_KEYLEN;
    prvKey.key.rsaPrv.dLen = RSA_MIN_KEYLEN + 1;
    assert_int_equal(CRYPT_EAL_PkeySetPrv(pkey, &prvKey), CRYPT_RSA_ERR_KEY_BITS);

    prvKey.key.rsaPrv.dLen = RSA_MIN_KEYLEN;
    prvD[0] = 0;
    assert_int_equal(CRYPT_EAL_PkeySetPrv(pkey, &prvKey), CRYPT_SUCCESS);

    prvKey.key.rsaPrv.nLen = RSA_MAX_KEYLEN;
    prvKey.key.rsaPrv.dLen = RSA_MAX_KEYLEN;
    assert_int_equal(CRYPT_EAL_PkeySetPrv(pkey, &prvKey), CRYPT_SUCCESS);

    CRYPT_EAL_RandDeinit();
    CRYPT_EAL_PkeyFreeCtx(pkey);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_RSA_SET_PUB_API_TC001(void **state)
{
    (void)state;

    uint8_t e[] = {1, 0, 1};
    CRYPT_EAL_PkeyPara para = {0};
    CRYPT_EAL_PkeyPub pubKey;
    uint8_t pubE[600];
    uint8_t pubN[2500];
    SetRsaPara(&para, e, 3, 1024);
    SetRsaPubKey(&pubKey, pubN, 600, pubE, 600);

    assert_int_equal(RandInit(), CRYPT_SUCCESS);

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_PkeyCtx *pkeyA =
        CRYPT_EAL_ProviderPkeyNewCtx(libctx, CRYPT_PKEY_RSA, CRYPT_EAL_PKEY_KEYMGMT_OPERATE, "provider=kaev1");
    assert_non_null(pkeyA);
    CRYPT_EAL_PkeyCtx *pkeyB =
        CRYPT_EAL_ProviderPkeyNewCtx(libctx, CRYPT_PKEY_RSA, CRYPT_EAL_PKEY_KEYMGMT_OPERATE, "provider=kaev1");
    assert_non_null(pkeyB);

    assert_int_equal(CRYPT_EAL_PkeySetPara(pkeyA, &para), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_PkeySetPara(pkeyB, &para), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_PkeyGen(pkeyA), CRYPT_SUCCESS);

    assert_int_equal(CRYPT_EAL_PkeyGetPub(pkeyA, &pubKey), CRYPT_SUCCESS);
    pubKey.key.rsaPub.nLen = 2049;
    assert_int_equal(CRYPT_EAL_PkeySetPub(pkeyB, &pubKey), CRYPT_RSA_ERR_KEY_BITS);

    pubKey.key.rsaPub.nLen = 600; // 600 bytes > 1024 bits

    assert_int_equal(CRYPT_EAL_PkeyGetPub(pkeyA, &pubKey), CRYPT_SUCCESS);
    pubKey.key.rsaPub.n = NULL;
    assert_int_equal(CRYPT_EAL_PkeySetPub(pkeyB, &pubKey), CRYPT_NULL_INPUT);

    pubKey.key.rsaPub.n = pubN;
    assert_int_equal(CRYPT_EAL_PkeyGetPub(pkeyA, &pubKey), CRYPT_SUCCESS);
    (void)memset_s(pubN, sizeof(pubN), 0x00, sizeof(pubN));
    assert_int_equal(CRYPT_EAL_PkeySetPub(pkeyB, &pubKey), CRYPT_RSA_ERR_KEY_BITS);

    assert_int_equal(CRYPT_EAL_PkeyGetPub(pkeyA, &pubKey), CRYPT_SUCCESS);
    pubKey.key.rsaPub.e = NULL;
    assert_int_equal(CRYPT_EAL_PkeySetPub(pkeyB, &pubKey), CRYPT_NULL_INPUT);

    pubKey.key.rsaPub.e = pubE;
    assert_int_equal(CRYPT_EAL_PkeyGetPub(pkeyA, &pubKey), CRYPT_SUCCESS);
    (void)memset_s(pubE, sizeof(pubE), 0x00, sizeof(pubE));
    assert_int_equal(CRYPT_EAL_PkeySetPub(pkeyB, &pubKey), CRYPT_RSA_ERR_INPUT_VALUE);

    CRYPT_EAL_RandDeinit();
    CRYPT_EAL_PkeyFreeCtx(pkeyA);
    CRYPT_EAL_PkeyFreeCtx(pkeyB);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_RSA_SET_PUB_API_TC002(void **state)
{
    (void)state;

    uint8_t pubE[2050]; // max rsa key len is 16384 bits, 16384/8 = 2048, 2050 > 2048
    uint8_t pubN[2050]; // max rsa key len is 16384 bits, 16384/8 = 2048, 2050 > 2048

    CRYPT_EAL_PkeyPub pubKey = {0};

    SetRsaPubKey(&pubKey, pubN, RSA_MIN_KEYLEN, pubE, RSA_MIN_KEYLEN);

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_PkeyCtx *pkey =
        CRYPT_EAL_ProviderPkeyNewCtx(libctx, CRYPT_PKEY_RSA, CRYPT_EAL_PKEY_KEYMGMT_OPERATE, "provider=kaev1");
    assert_non_null(pkey);

    (void)memset_s(pubE, sizeof(pubE), 0xff, sizeof(pubE));
    (void)memset_s(pubN, sizeof(pubN), 0xff, sizeof(pubN));
    assert_int_equal(CRYPT_EAL_PkeySetPub(pkey, &pubKey), CRYPT_RSA_ERR_INPUT_VALUE);

    pubKey.key.rsaPub.nLen = RSA_MIN_KEYLEN - 1;
    assert_int_equal(CRYPT_EAL_PkeySetPub(pkey, &pubKey), CRYPT_RSA_ERR_KEY_BITS);

    pubKey.key.rsaPub.nLen = RSA_MAX_KEYLEN;
    pubKey.key.rsaPub.eLen = RSA_MAX_KEYLEN + 1;
    assert_int_equal(CRYPT_EAL_PkeySetPub(pkey, &pubKey), CRYPT_RSA_ERR_KEY_BITS);

    pubKey.key.rsaPub.nLen = RSA_MAX_KEYLEN + 1;
    pubKey.key.rsaPub.eLen = RSA_MAX_KEYLEN;
    assert_int_equal(CRYPT_EAL_PkeySetPub(pkey, &pubKey), CRYPT_RSA_ERR_KEY_BITS);

    pubKey.key.rsaPub.nLen = RSA_MIN_KEYLEN;
    pubKey.key.rsaPub.eLen = RSA_MIN_KEYLEN + 1;
    assert_int_equal(CRYPT_EAL_PkeySetPub(pkey, &pubKey), CRYPT_RSA_ERR_KEY_BITS);

    pubE[0] = 0;
    pubKey.key.rsaPub.eLen = RSA_MIN_KEYLEN;
    assert_int_equal(CRYPT_EAL_PkeySetPub(pkey, &pubKey), CRYPT_SUCCESS);

    pubKey.key.rsaPub.nLen = RSA_MAX_KEYLEN;
    pubKey.key.rsaPub.eLen = RSA_MAX_KEYLEN;
    assert_int_equal(CRYPT_EAL_PkeySetPub(pkey, &pubKey), CRYPT_RSA_ERR_KEY_BITS);

    (void)memset_s(pubE, sizeof(pubE), 0, sizeof(pubE));
    assert_int_equal(CRYPT_EAL_PkeySetPub(pkey, &pubKey), CRYPT_RSA_ERR_INPUT_VALUE);

    pubE[RSA_MAX_KEYLEN - 1] = 1;
    assert_int_equal(CRYPT_EAL_PkeySetPub(pkey, &pubKey), CRYPT_RSA_ERR_INPUT_VALUE);

    CRYPT_EAL_PkeyFreeCtx(pkey);
    CRYPT_EAL_LibCtxFree(libctx);
}

static CRYPT_RSA_Test SDV_KAE_RSA_ENC_API_TC001_HEX[] = {
    {
        "909d1c40da8b0840be7d0e626539c5884f907b505d7e573deeee1d66c5b73e6a38f376aaf4cdd97441034e9a7f055d5b53f93567393364cdc591b8f86668cae2a5fb1432eac3883381e7cd299c7dbaaba74a22a02263678be43ccc01cb936b20f7c968284524691f1ffa28ad8f00a8a929da99bc4b3bd757743912e5de708851",
        "010001",
        NULL,
        CRYPT_MD_SHA1,
        "d436e99569fd32a7c8a05bbc90d32c49",
        NULL,
    },
};

static void SDV_KAE_RSA_ENC_API_TC001(void **state)
{
    CRYPT_RSA_Test *test = (CRYPT_RSA_Test *)*state;
    Hex *n = NewHex();
    Hex *e = NewHex();
    int32_t hashId = test->hashId;
    Hex *in = NewHex();

    assert_int_equal(ConvertHex(test->n, n), 0);
    assert_int_equal(ConvertHex(test->e, e), 0);
    assert_int_equal(ConvertHex(test->in, in), 0);

    uint8_t crypt[TMP_BUFF_LEN];
    uint32_t cryptLen = TMP_BUFF_LEN;
    CRYPT_EAL_PkeyPub pubkey = {0};
    BSL_Param oaepParam[3] = {{CRYPT_PARAM_RSA_MD_ID, BSL_PARAM_TYPE_INT32, &hashId, sizeof(hashId), 0},
                              {CRYPT_PARAM_RSA_MGF1_ID, BSL_PARAM_TYPE_INT32, &hashId, sizeof(hashId), 0},
                              BSL_PARAM_END};

    SetRsaPubKey(&pubkey, n->x, n->len, e->x, e->len);

    assert_int_equal(RandInit(), CRYPT_SUCCESS);

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_PkeyCtx *pkey = CRYPT_EAL_ProviderPkeyNewCtx(
        libctx, CRYPT_PKEY_RSA, CRYPT_EAL_PKEY_KEYMGMT_OPERATE + CRYPT_EAL_PKEY_CIPHER_OPERATE, "provider=kaev1");
    assert_non_null(pkey);

    assert_int_equal(CRYPT_EAL_PkeyEncrypt(pkey, in->x, in->len, crypt, &cryptLen), CRYPT_RSA_NO_KEY_INFO);

    assert_int_equal(CRYPT_EAL_PkeySetPub(pkey, &pubkey), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_PkeyEncrypt(pkey, in->x, in->len, crypt, &cryptLen), CRYPT_RSA_PAD_NO_SET_ERROR);

    assert_int_equal(CRYPT_EAL_PkeyCtrl(pkey, CRYPT_CTRL_SET_RSA_RSAES_OAEP, oaepParam, 0), CRYPT_SUCCESS);

    assert_int_equal(CRYPT_EAL_PkeyEncrypt(NULL, in->x, in->len, crypt, &cryptLen), CRYPT_NULL_INPUT);
    assert_int_equal(CRYPT_EAL_PkeyEncrypt(pkey, NULL, in->len, crypt, &cryptLen), CRYPT_NULL_INPUT);
    assert_int_equal(CRYPT_EAL_PkeyEncrypt(pkey, in->x, 0, crypt, &cryptLen), CRYPT_SUCCESS);
    // inLen > k-2hashLen-2 , 87 = (128 - 2 * 20 - 2)
    assert_int_equal(CRYPT_EAL_PkeyEncrypt(pkey, in->x, 87, crypt, &cryptLen), CRYPT_RSA_ERR_ENC_BITS);
    assert_int_equal(CRYPT_EAL_PkeyEncrypt(pkey, in->x, in->len, NULL, &cryptLen), CRYPT_NULL_INPUT);
    assert_int_equal(CRYPT_EAL_PkeyEncrypt(pkey, in->x, in->len, crypt, NULL), CRYPT_NULL_INPUT);
    cryptLen = 0;
    assert_int_equal(CRYPT_EAL_PkeyEncrypt(pkey, in->x, in->len, crypt, &cryptLen), CRYPT_RSA_BUFF_LEN_NOT_ENOUGH);

    FreeHex(n);
    FreeHex(e);
    FreeHex(in);
    CRYPT_EAL_RandDeinit();
    CRYPT_EAL_PkeyFreeCtx(pkey);
    CRYPT_EAL_LibCtxFree(libctx);
}

static CRYPT_RSA_Test SDV_KAE_RSA_DEC_API_TC001_HEX[] = {
    {
        "c5062b58d8539c765e1e5dbaf14cf75dd56c2e13105fecfd1a930bbb5948ff328f126abe779359ca59bca752c308d281573bc6178b6c0fef7dc445e4f826430437b9f9d790581de5749c2cb9cb26d42b2fee15b6b26f09c99670336423b86bc5bec71113157be2d944d7ff3eebffb28413143ea36755db0ae62ff5b724eecb3d316b6bac67e89cacd8171937e2ab19bd353a89acea8c36f81c89a620d5fd2effea896601c7f9daca7f033f635a3a943331d1b1b4f5288790b53af352f1121ca1bef205f40dc012c412b40bdd27585b946466d75f7ee0a7f9d549b4bece6f43ac3ee65fe7fd37123359d9f1a850ad450aaf5c94eb11dea3fc0fc6e9856b1805ef",
        NULL,
        "49e5786bb4d332f94586327bde088875379b75d128488f08e574ab4715302a87eea52d4c4a23d8b97af7944804337c5f55e16ba9ffafc0c9fd9b88eca443f39b7967170ddb8ce7ddb93c6087c8066c4a95538a441b9dc80dc9f7810054fd1e5c9d0250c978bb2d748abe1e9465d71a8165d3126dce5db2adacc003e9062ba37a54b63e5f49a4eafebd7e4bf5b0a796c2b3a950fa09c798d3fa3e86c4b62c33ba9365eda054e5fe74a41f21b595026acf1093c90a8c71722f91af1ed29a41a2449a320fc7ba3120e3e8c3e4240c04925cc698ecd66c7c906bdf240adad972b4dff4869d400b5d13e33eeba38e075e872b0ed3e91cc9c283867a4ffc3901d2069f",
        CRYPT_MD_SHA1,
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
        NULL,
    },
};

static void SDV_KAE_RSA_DEC_API_TC001(void **state)
{
    CRYPT_RSA_Test *test = (CRYPT_RSA_Test *)*state;
    Hex *n = NewHex();
    Hex *d = NewHex();
    int32_t hashId = test->hashId;
    Hex *in = NewHex();

    assert_int_equal(ConvertHex(test->n, n), 0);
    assert_int_equal(ConvertHex(test->d, d), 0);
    assert_int_equal(ConvertHex(test->in, in), 0);

    uint8_t crypt[TMP_BUFF_LEN];
    uint32_t cryptLen = TMP_BUFF_LEN;
    CRYPT_EAL_PkeyPrv prvkey = {0};
    BSL_Param oaepParam[3] = {{CRYPT_PARAM_RSA_MD_ID, BSL_PARAM_TYPE_INT32, &hashId, sizeof(hashId), 0},
                              {CRYPT_PARAM_RSA_MGF1_ID, BSL_PARAM_TYPE_INT32, &hashId, sizeof(hashId), 0},
                              BSL_PARAM_END};
    SetRsaPrvKey(&prvkey, n->x, n->len, d->x, d->len);

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_PkeyCtx *pkey = CRYPT_EAL_ProviderPkeyNewCtx(
        libctx, CRYPT_PKEY_RSA, CRYPT_EAL_PKEY_KEYMGMT_OPERATE + CRYPT_EAL_PKEY_CIPHER_OPERATE, "provider=kaev1");
    assert_non_null(pkey);

    assert_int_equal(CRYPT_EAL_PkeyDecrypt(pkey, in->x, in->len, crypt, &cryptLen), CRYPT_RSA_NO_KEY_INFO);

    assert_int_equal(CRYPT_EAL_PkeySetPrv(pkey, &prvkey), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_PkeyDecrypt(pkey, in->x, in->len, crypt, &cryptLen), CRYPT_RSA_PAD_NO_SET_ERROR);

    assert_int_equal(CRYPT_EAL_PkeyCtrl(pkey, CRYPT_CTRL_SET_RSA_RSAES_OAEP, oaepParam, 0), CRYPT_SUCCESS);

    assert_int_equal(CRYPT_EAL_PkeyDecrypt(NULL, in->x, in->len, crypt, &cryptLen), CRYPT_NULL_INPUT);
    assert_int_equal(CRYPT_EAL_PkeyDecrypt(pkey, NULL, in->len, crypt, &cryptLen), CRYPT_NULL_INPUT);
    assert_int_equal(CRYPT_EAL_PkeyDecrypt(pkey, in->x, 0, crypt, &cryptLen), CRYPT_RSA_ERR_DEC_BITS);
    const uint32_t invalidInLen = 1025; // 1025: invalid data length
    assert_int_equal(CRYPT_EAL_PkeyDecrypt(pkey, in->x, invalidInLen, crypt, &cryptLen), CRYPT_RSA_ERR_DEC_BITS);
    assert_int_equal(CRYPT_EAL_PkeyDecrypt(pkey, in->x, in->len, NULL, &cryptLen), CRYPT_NULL_INPUT);
    assert_int_equal(CRYPT_EAL_PkeyDecrypt(pkey, in->x, in->len, crypt, NULL), CRYPT_NULL_INPUT);

    cryptLen = 0;
    assert_int_equal(CRYPT_EAL_PkeyDecrypt(pkey, in->x, in->len, crypt, &cryptLen), CRYPT_RSA_ERR_INPUT_VALUE);
    cryptLen = 2049; // 2049 is an invalid data length.
    assert_int_equal(CRYPT_EAL_PkeyDecrypt(pkey, in->x, in->len, crypt, &cryptLen), CRYPT_RSA_ERR_INPUT_VALUE);

    FreeHex(n);
    FreeHex(d);
    FreeHex(in);
    CRYPT_EAL_RandDeinit();
    CRYPT_EAL_PkeyFreeCtx(pkey);
    CRYPT_EAL_LibCtxFree(libctx);
}

int main(void)
{
    struct CMUnitTest tests[GROUP_TEST_MAX] = {NULL};
    int testCnt = 0;

    tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test(SDV_KAE_RSA_PROVIDER_LOAD);
    tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test(SDV_KAE_RSA_NEW_API_TC001);
    tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test(SDV_KAE_RSA_PARA_API_TC001);
    for (size_t i = 0; i < sizeof(SDV_KAE_RSA_PARA_API_TC002_VEC) / sizeof(SDV_KAE_RSA_PARA_API_TC002_VEC[0]); i++) {
        tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_RSA_PARA_API_TC002,
                                                                        &SDV_KAE_RSA_PARA_API_TC002_VEC[i]);
    }
    tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test(SDV_KAE_RSA_PARA_API_TC003);
    tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test(SDV_KAE_RSA_GEN_API_TC001);
    tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test(SDV_KAE_RSA_GET_PUB_API_TC001);
    tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test(SDV_KAE_RSA_GET_PRV_API_TC001);
    tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test(SDV_KAE_RSA_SET_PRV_API_TC001);
    tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test(SDV_KAE_RSA_SET_PRV_API_TC002);
    tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test(SDV_KAE_RSA_SET_PUB_API_TC001);
    tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test(SDV_KAE_RSA_SET_PUB_API_TC002);
    for (size_t i = 0; i < sizeof(SDV_KAE_RSA_ENC_API_TC001_HEX) / sizeof(SDV_KAE_RSA_ENC_API_TC001_HEX[0]); i++) {
        tests[testCnt++] =
            (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_RSA_ENC_API_TC001, &SDV_KAE_RSA_ENC_API_TC001_HEX[i]);
    }
    for (size_t i = 0; i < sizeof(SDV_KAE_RSA_DEC_API_TC001_HEX) / sizeof(SDV_KAE_RSA_DEC_API_TC001_HEX[0]); i++) {
        tests[testCnt++] =
            (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_RSA_DEC_API_TC001, &SDV_KAE_RSA_DEC_API_TC001_HEX[i]);
    }
    cmocka_run_group_tests(tests, NULL, NULL);
    return 0;
}